﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Diagnostics;


namespace Microsoft.Mtool.FSM
{
    public class PictFile
    {
        private string pictBinPath;
        private string pictWorkFolder;
        private string pictTmpFilePath;
        private List<PictInputVariable> inputs = new List<PictInputVariable>();

        public PictFile(string pictBinaryPath, string workFolder)
        { 
            pictBinPath = pictBinaryPath;
            pictWorkFolder = workFolder.EndsWith("\\") ? workFolder : workFolder + "\\";
            pictTmpFilePath = pictWorkFolder + "tmp.input";
        }

        public List<PictInputVariable> Inputs
        {
            get { return inputs; }
            set { inputs = value; }
        }

        public List<PictOutputVarList> RunPict()
        {
            return RunPict(GetPictInputFileContents());
        }
         
        public List<PictOutputVarList> RunPict(string pictContents)
        {
            WriteTmpFile(pictContents);
            Process p = new Process();
            p.StartInfo = new ProcessStartInfo(pictBinPath, pictTmpFilePath);
            p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            p.StartInfo.CreateNoWindow = true;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.UseShellExecute = false;
            if (p.Start())
            {
                p.WaitForExit(10000);                
                return GetPictOutputFileContents(p.StandardOutput);
            }
            return null;
        }

        public void AddInput(string key, int order, params string[] values)
        {
            //if (inputs.Contains(key))
            //{
            //    throw new Exception("Input with this name already exists!");
            //}

            inputs.Add(new PictInputVariable(key, new List<string>(values), order));
        }

        private List<PictOutputVarList> GetPictOutputFileContents(StreamReader outputReader)
        {
            StringBuilder sb = new StringBuilder();
            List<PictOutputVarList> retv = new List<PictOutputVarList>();
            foreach (PictInputVariable p in inputs)
            {
                sb.Append(p.Name).Append("\t");
            }
            string headerLine = sb.ToString().Trim();
            bool headerHit = false;

            while (!outputReader.EndOfStream)
            {
                string line = outputReader.ReadLine().Trim();
                if (!headerHit)
                {
                    if (line != headerLine)
                    {
                        //ignore the warning lines
                        Logger.Instance.Warn("Pict output contents ignored: suspect header :{0}", line);
                        continue;
                    }
                    else
                    {
                        headerHit = true;
                    }
                }
                else
                {
                    string[] values = line.Split(new string[] { " ", "\t" }, StringSplitOptions.RemoveEmptyEntries);
                    if (values.Length != inputs.Count)
                    {
                        Logger.Instance.Warn("Pict output contents ignored:{0}", line);
                        continue;
                    }
                    PictOutputVarList varList = new PictOutputVarList();
                    int ithV = 0;
                    foreach (string v in values)
                    {
                        //retv.Add(new PictOutputVariable(inputs[ithV].Name, v));
                        varList.Variables.Add(new PictOutputVariable(inputs[ithV++].Name, v));
                    }
                    retv.Add(varList);
                }
            }
            return retv;
        }

        private string GetPictInputFileContents()
        {
            StringBuilder sb = new StringBuilder();
            foreach (PictInputVariable v in inputs)
            {
                sb.Append(v.Name).Append(":");
                int ithValue = 0;
                if(v.Values.Count == 0)
                    sb.Append("null");
                foreach (string vv in v.Values)
                {
                    if (ithValue++ > 0)
                        sb.Append(',');
                    sb.Append(vv);
                }
                sb.AppendLine();
            }
            return sb.ToString();
        }

        private void WriteTmpFile(string pictContents)
        {            
            using (StreamWriter wter = new StreamWriter(pictTmpFilePath))
            {
                wter.Write(pictContents);
            }
        }
    }
}
